package com.roads.engineering.service.impl;

import com.roads.common.config.MasterConfig;
import com.roads.common.constant.Constants;
import com.roads.common.constant.UserConstants;
import com.roads.common.core.domain.entity.SysUser;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.file.FileUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.engineering.domain.EngMeterageChange;
import com.roads.engineering.domain.EngMeterageContract;
import com.roads.engineering.domain.EngMeterageExplain;
import com.roads.engineering.domain.EngMeterageMaster;
import com.roads.engineering.domain.EngMeterageOther;
import com.roads.engineering.mapper.EngMeterageChangeMapper;
import com.roads.engineering.mapper.EngMeterageContractMapper;
import com.roads.engineering.mapper.EngMeterageDetailAnnexMapper;
import com.roads.engineering.mapper.EngMeterageExplainMapper;
import com.roads.engineering.mapper.EngMeterageMasterMapper;
import com.roads.engineering.mapper.EngMeterageOtherMapper;
import com.roads.engineering.service.IEngMeterageDetailService;
import com.roads.engineering.service.IEngMeterageMasterService;
import com.roads.project.domain.ProCompany;
import com.roads.project.domain.ProInstitution;
import com.roads.project.domain.ProPaymentItems;
import com.roads.project.domain.ProProject;
import com.roads.project.mapper.ProCompanyMapper;
import com.roads.project.mapper.ProInstitutionMapper;
import com.roads.project.mapper.ProProjectMapper;
import com.roads.system.mapper.SysAnnexFileMapper;
import com.roads.system.mapper.SysUserMapper;
import com.roads.system.service.ISysMessageService;
import com.roads.workflow.domain.WorkflowMeterageNode;
import com.roads.workflow.domain.WorkflowTaskDelivery;
import com.roads.workflow.mapper.WorkflowMeterageNodeMapper;
import com.roads.workflow.service.IWorkflowTaskService;
import org.omg.CORBA.MARSHAL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.List;

/**
 * 工程计量Service业务层处理
 * 
 * @author nhp
 * @date 2022-02-25
 */
@Service
public class EngMeterageMasterServiceImpl implements IEngMeterageMasterService {

    @Autowired
    private EngMeterageMasterMapper mapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ProInstitutionMapper institutionMapper;

    @Autowired
    private ProProjectMapper projectMapper;

    @Autowired
    private ProCompanyMapper companyMapper;

    @Autowired
    private IWorkflowTaskService workflowTaskService;

    @Autowired
    private ISysMessageService messageService;

    @Autowired
    private SysAnnexFileMapper sysAnnexFileMapper;

    @Autowired
    private EngMeterageContractMapper detailContractMapper;

    @Autowired
    private EngMeterageChangeMapper detailChangeMapper;

    @Autowired
    private EngMeterageOtherMapper detailOtherMapper;

    @Autowired
    private EngMeterageExplainMapper detailExplainMapper;

    @Autowired
    private EngMeterageDetailAnnexMapper detailAnnexMapper;

    @Autowired
    private WorkflowMeterageNodeMapper workflowMeterageNodeMapper;

    @Autowired
    private IEngMeterageDetailService detailService;

    /**
     * 根据主键ID查询详情
     * 
     * @param id 工程计量主键
     * @return 工程计量
     */
    @Override
    public EngMeterageMaster getModelById(Long id) {
        return mapper.getModelById(id);
    }

    /**
     * 根据uuid查询详情
     *
     * @param uuid 工程计量uuid
     * @return 工程计量
     */
    @Override
    public EngMeterageMaster getModelByUuid(String uuid) {
        return mapper.getModelByUuid(uuid);
    }

    /**
     * 查询列表
     * 
     * @param model 工程计量
     * @return 工程计量
     */
    @Override
    public List<EngMeterageMaster> selectModelList(EngMeterageMaster model) {
        return mapper.selectModelList(model);
    }

    /**
     * 校验申请编号是否唯一
     *
     * @param model 工程计量
     * @return 结果
     */
    @Override
    public String checkApplyCodeUnique(EngMeterageMaster model) {
        Long masterId = StringUtils.isNull(model.getMasterId()) ? -1L : model.getMasterId();
        EngMeterageMaster search = mapper.checkApplyCodeUnique(model.getApplyCode());
        if (StringUtils.isNotNull(search) && !search.getMasterId().equals(masterId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增
     * 
     * @param model 工程计量
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(EngMeterageMaster model) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 获取流程实例
        WorkflowMeterageNode workflowMeterageNode = workflowMeterageNodeMapper.getModelByBeginNodeAndUser(loginUser.getUserName(), Constants.WORKFLOW_TYPE_ENGINEERING);
        // 任务uuid
        String uuid = IdUtils.simpleUuid();
        // 设置 标段名称，项目名称，单位名称
        ProInstitution bid = institutionMapper.getModelByInnerCode(model.getInstitutionCode());
        model.setInstitutionName(bid.getInstitutionName());
        ProProject project = projectMapper.selectProProjectByProjectId(bid.getProjectId());
        model.setProjectId(project.getProjectId());
        model.setProjectName(project.getProjectName());
        ProCompany company = companyMapper.selectProCompanyByCompanyId(bid.getCompanyId());
        model.setCompanyName(company.getCompanyName());
        // 设置当前部门和用户名称
        model.setCurrentDeptName(loginUser.getDept().getDeptName());
        model.setCurrentUser(loginUser.getUserName());
        model.setCurrentDept(loginUser.getDeptId());
        model.setCurrentUserName(loginUser.getNickName());
        model.setCreateBy(loginUser.getUserName());
        model.setCreateTime(DateUtils.getNowDate());
        model.setUuid(uuid);
        model.setWorkflowUuid(workflowMeterageNode.getWorkflowUuid());
        mapper.insert(model);
        // 添加工程支付项目
        ProPaymentItems search = new ProPaymentItems();
        search.setProjectId(project.getProjectId());
        search.setComputeMode(Constants.FIXED_VALUE);
        search.setItemStatus(Constants.SUCCESS);
        List<EngMeterageOther> others = detailService.createMeterageOtherList(model, loginUser);
        detailOtherMapper.insertBatch(others);
        // 添加填报说明
        EngMeterageExplain explain = new EngMeterageExplain();
        explain.setMasterId(model.getMasterId());
        explain.setDept(loginUser.getDeptId());
        explain.setDeptName(loginUser.getDept().getDeptName());
        explain.setUser(loginUser.getUserName());
        explain.setUserName(loginUser.getNickName());
        explain.setCreateBy(SecurityUtils.getUsername());
        explain.setCreateTime(DateUtils.getNowDate());
        detailExplainMapper.insert(explain);
        // 创建流程
        workflowTaskService.createTask(uuid, Constants.WORKFLOW_TYPE_ENGINEERING, Constants.MENU_TYPE_ENGINEERING, loginUser, workflowMeterageNode);
        return 1;
    }

    /**
     * 修改
     * 
     * @param model 工程计量
     * @return 结果
     */
    @Override
    public int update(EngMeterageMaster model) {
        model.setUpdateTime(DateUtils.getNowDate());
        return mapper.update(model);
    }

    /**
     * 批量删除
     * 
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            // 查找主表信息
            EngMeterageMaster master = mapper.getModelById(ids[i]);
            String uuid = master.getUuid();
            // 删除主表信息
            mapper.delete(ids[i]);
            // 删除流程
            workflowTaskService.deleteTask(uuid);
            // 删除消息
            messageService.deleteByUuid(uuid);
            // 删除附件记录
            sysAnnexFileMapper.deleteByUuid(uuid);
            // 删除附件文件 其中包含明细里的草图和附件
            String filePath = MasterConfig.getUploadAnnexPath() + "/" + Constants.MENU_TYPE_ENGINEERING + "/" + uuid;
            FileUtils.deleteDirectory(new File(filePath));
            // 删除明细
            deleteDetail(master);
        }
        return 1;
    }

    /**
     * 删除工程计量明细
     *
     * @param master 主表实体
     */
    private void deleteDetail(EngMeterageMaster master) {
        // 删除工程计量--合同计量
        deleteDetailContract(master);
        // 删除工程计量--变更计量
        deleteDetailChange(master);
        // 删除工程计量--其他支付项目
        deleteDetailOther(master);
        // 删除工程计量--填报说明
        deleteDetailExplain(master);
    }

    /**
     * 删除工程计量--合同计量
     * @param master 主表实体
     */
    private void deleteDetailContract(EngMeterageMaster master) {
        // 删除附件记录
        detailAnnexMapper.deleteContractAnnexByMasterId(master.getMasterId());
        // 还原工程量清单
        detailContractMapper.restore(master.getMasterId(), SecurityUtils.getUsername());
        // 删除合同计量清单
        detailContractMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除工程计量--合同计量
     * @param master 主表实体
     */
    private void deleteDetailChange(EngMeterageMaster master) {
        // 删除附件记录
        detailAnnexMapper.deleteContractAnnexByMasterId(master.getMasterId());
        // 还原工程量清单
        detailChangeMapper.restore(master.getMasterId(), SecurityUtils.getUsername());
        // 删除合同计量清单
        detailChangeMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除工程计量--合同计量
     * @param master 主表实体
     */
    private void deleteDetailOther(EngMeterageMaster master) {
        detailOtherMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除工程计量--填报说明
     * @param master 主表实体
     */
    private void deleteDetailExplain(EngMeterageMaster master){
        detailExplainMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除
     * 
     * @param id 工程计量主键
     * @return 结果
     */
    @Override
    public int delete(Long id) {
        return mapper.delete(id);
    }

    /**
     * 传送
     *
     * @param delivery 传送对象
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delivery(WorkflowTaskDelivery delivery) {
        // 当前登录用户
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 主表处理 修改当前部门和当前用户
        EngMeterageMaster master = mapper.getModelByUuid(delivery.getTaskUuid());
        // 传送至哪个用户，非当前登录用户
        SysUser deliveryUser = userMapper.selectUserByUserName(delivery.getUser());
        master.setCurrentDept(deliveryUser.getDeptId());
        master.setCurrentDeptName(deliveryUser.getDept().getDeptName());
        master.setCurrentUser(deliveryUser.getUserName());
        master.setCurrentUserName(deliveryUser.getNickName());
        mapper.update(master);
        // 传送明细
        deliveryDetail(master, loginUser, deliveryUser);
        // 流程处理
        workflowTaskService.deliveryTask(delivery, loginUser, deliveryUser);
        // 消息处理
        messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        messageService.createDeliveryMessage(
                master.getUuid(),
                deliveryUser.getUserName(),
                "/engineering/meterage",
                "由" + loginUser.getNickName() + "传送的工程计量",
                loginUser.getUserName());
        return 1;
    }

    /**
     * 传送明细
     * 合同清单传送，变更清单传送，其他支付项目传送，材料清单传送
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetail(EngMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        // 传送--合同清单
        deliveryDetailContract(master, loginUser, deliveryUser);
        // 传送--变更清单
        deliveryDetailChange(master, loginUser, deliveryUser);
        // 传送--其他支付项目
        deliveryDetailOther(master, loginUser, deliveryUser);
        // 传送--填报说明
        deliveryDetailExplain(master, loginUser, deliveryUser);
    }

    /**
     * 传送--合同清单
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailContract(EngMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        EngMeterageContract search = new EngMeterageContract();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailContractMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<EngMeterageContract> details = detailContractMapper.selectModelList(search);
        for (EngMeterageContract detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailContractMapper.insertBatch(details);
        }

    }

    /**
     * 传送--变更清单
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailChange(EngMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        EngMeterageChange search = new EngMeterageChange();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailChangeMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<EngMeterageChange> details = detailChangeMapper.selectModelList(search);
        for (EngMeterageChange detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailChangeMapper.insertBatch(details);
        }
    }

    /**
     * 传送--其他支付项目
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailOther(EngMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        EngMeterageOther search = new EngMeterageOther();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailOtherMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<EngMeterageOther> details = detailOtherMapper.selectModelList(search);
        for (EngMeterageOther detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailOtherMapper.insertBatch(details);
        }
    }

    /**
     * 传送--填报说明
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailExplain(EngMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        EngMeterageExplain search = new EngMeterageExplain();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailExplainMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        EngMeterageExplain detail = detailExplainMapper.getModelByUser(master.getMasterId(), loginUser.getUserName());
        detail.setDetailExplainId(null);
        detail.setDept(deliveryUser.getDeptId());
        detail.setDeptName(deliveryUser.getDept().getDeptName());
        detail.setUser(deliveryUser.getUserName());
        detail.setUserName(deliveryUser.getNickName());
        detailExplainMapper.insert(detail);
    }

    /**
     * 批量锁定
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int lock(Long[] ids) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 循环处理锁定数据
        for (int i = 0; i < ids.length; i++) {
            long masterId = ids[i];
            // 主表状态处理
            EngMeterageMaster master = mapper.getModelById(masterId);
            master.setStatus(Constants.LOCK);
            mapper.update(master);
            // 完成流程处理
            workflowTaskService.finishTask(master.getUuid(), loginUser);
            // 消息处理
            messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        }
        return 1;
    }

    /**
     * 解锁
     *
     * @param master 主表
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int unlock(EngMeterageMaster master, Long id) {
        master.setStatus(Constants.UNLOCK);
        mapper.update(master);
        // 删除流程完成信息
        workflowTaskService.deleteFinishTask(master.getUuid());
        // 当前数据所在位置的消息改正未读状态
        messageService.updateMessageStatusByUnread(master.getUuid(), master.getCurrentUser());
        return 1;
    }


    /**
     * 查询当前登录用户在计量流程开始节点出现的次数
     * @param user 当前登录用户
     * @return 数量
     */
    @Override
    public int getCountWorkflowNodeUserForBeginNode(String user) {
        return mapper.getCountWorkflowNodeUserForBeginNode(user);
    }

}
